#ifndef __M_BUFFER__
#define __M_BUFFER__

#include <iostream>
#include <vector>
#include <assert.h>

/*
    缓冲区类的设计

    提供的操作:
        1.向缓冲区写入数据
        2.获取可读数据起始地址的数据
        3.获取可读数据长度的接口
        4.移动读写位置的接口
        5.初始化缓冲区的操作
        6.提供交换缓冲区的接口
*/

namespace log//注意log可能与algorithm文件里面的某个名字冲突,解决方法,不引用该头文件,或者改名，或者外面再套一层命名空间
{           //用了copy函数也会导致冲突，因为copy函数在algorithm文件里面
    class Buffer
    {
        #define BUFFER_DEFAULT_SIZE (1 * 1024 * 1024)
        #define BUFFER_INCREMENT_SIZE (1 * 1024 * 1024)
        #define BUFFER_THRESHOLD_SIZE (10 * 1024 * 1024)
        public:
            Buffer()
                :_v(BUFFER_DEFAULT_SIZE)
                ,_Read_Idx(0)
                ,_Write_Idx(0)
            {}
            size_t WriteAble() { return _v.size() - _Write_Idx; }//返回可以写的字符数
            size_t ReadAble() { return _Write_Idx - _Read_Idx; }//返回可以读的字符数
            void resset() { _Read_Idx = _Write_Idx = 0; }//初始化
            bool empty() { return _Write_Idx == _Read_Idx; }//判断是否为空
            void push(const char* data,size_t len)
            {
                EnsureEnoughSpace(len);//这里只管扩容,如果是异步安全模式下,在AsyncWorker.hpp里面,如果缓冲区可写的大小小于要写入字符串的大小,会阻塞,等待日志落地,根本不会来到这里扩容,如果是性能模式,本质就是要扩容
                std::copy(data,data + len, &_v[_Write_Idx]);
                _Write_Idx += len;
            }
            void pop(size_t len)
            {
                _Read_Idx += len;
                assert(_Read_Idx <= _Write_Idx);//防止删除过多
            }
            void swap(Buffer& buffer)//交换两个缓冲区
            {
                std::swap(_v,buffer._v);
                std::swap(_Read_Idx,buffer._Read_Idx);
                std::swap(_Write_Idx,buffer._Write_Idx);
            }
            const char* begin() { return &_v[_Read_Idx]; }
        private:
            void EnsureEnoughSpace(int len)//保证有足够的空间
            {
                if(len < WriteAble()) return;

                size_t NewSize;
                if(_v.size() < BUFFER_DEFAULT_SIZE)
                    NewSize = _v.size() * 2 + len;//保证在存下len的前提下再扩容,留有更多的空间,小于阈值就翻倍增长
                else
                    NewSize = _v.size() + BUFFER_INCREMENT_SIZE + len;//大于阈值就线性增长
                
                _v.resize(NewSize);
            }
        private:
            std::vector<char> _v;
            size_t _Read_Idx;
            size_t _Write_Idx;
    };
}


#endif